#include "QbCefQueryHandler.h"
#include <QJsonDocument>
#include <QJsonObject>
#include <QJsonArray>
#include <QCefView.h>

#include "../QbBondModule.h"
#include <include/CmdDefines.h>
#include "TdsReqHandler.h"
#include "QbWebHandler.h"
#include "QbPageOpenHandler.h"

#include "core/QbLogger.h"


QString /*error_string*/ onCaptureScreenshotRequest(QCefView *web_view, const QRect& rect, const QCefQuery &query)
{
    int shot_id = -1;
    QMetaObject::Connection conn = QObject::connect(
        web_view, &QCefView::screenshotCaptured,
        [web_view, query](int /*screenshot_id*/, bool success, const QString& result) {
            // assert shot_id == screenshot_id
            int error = success ? 0 : 1011;
            query.reply(success, result, error);
            QObject::disconnect(web_view, &QCefView::screenshotCaptured, nullptr, nullptr);
        });

    if (bool(conn)) {
        shot_id = web_view->captureScreenshot(rect);
        if (shot_id <= 0) // Failed
        {
            QObject::disconnect(conn);
            return "Failed to call QCefView::captureScreenshot";
        }

        return ""; // success
    }

    return "Failed to connect QCefView::screenshotCaptured";
}


QbCefViewDelegate::QbCefViewDelegate(): CefViewDelegate(), TdsReqHandler()
{

}

void QbCefViewDelegate::onCefQuery(int browserId, qint64 frameId, const QCefQuery &query)
{
    const QString& request = query.request();
    // TODO: dispatch the request
    QJsonDocument doc = QJsonDocument::fromJson(QByteArray(request.toUtf8()));

    const QJsonArray& j3_req = doc.array();
    const QString& category = j3_req[0].toString();
    const QJsonArray& value = j3_req[1].toArray();

    QString response = "";
    int error = 0;
    while(1){
        {
            QbWebHandler h;
            if (h.webHandlerFunc(category, value, error, response)) {
                break;
            }
        }

        if (category == "open_page") {
            QbPageOpenHandler h;
            error = h.open_page(value, response);
            break;
        }

        if (category == "captureScreenshot") {
            CefViewWidget* ptr_ = getCefViewWidget(browserId);
            if (ptr_ == nullptr) {
                error = 1010;
                response = "Inner Error: web_view is null.";
                break;
            }

            const QJsonObject& parameters = value[0].toObject();
            const QJsonArray& top_left = parameters["top_left"].toArray();
            const QJsonArray& bottom_right = parameters["bottom_right"].toArray();
            if ((top_left.size() != 2) || (bottom_right.size() != 2)) {
                error = 1011;
                response = "Invalid Parameters for captureScreenshot.";
                break;
            }
            QRect rect(QPoint(top_left[0].toInt(), top_left[1].toInt()),
                       QPoint(bottom_right[0].toInt(), bottom_right[1].toInt()));
            response = onCaptureScreenshotRequest(ptr_, rect, query);
            if (response.isEmpty()) {
                // query is captured and the reply will be sent later.
                return;
            }
            error = 1012;
            break;
        }

        if (category == "sendMouseMoveEvent") {
            break;
        }

        if (category == "copyImage2ClipBoard") {
            break;
        }

        if (TdsReqHandler::webHandlerFunc(browserId, frameId, category, value, error, response)) {
            break;
        }

        error = 9999;
        response = "Invalid CefQuery Request";
        break;
    }

    query.reply(error == 0, response, error);
    if (9999 == error)
        log_warning("QbCefQueryHandler::onCefQueryRequest: request=%s | error=%d, response=%s", request.toStdString().c_str(), error, response.toStdString().c_str());

}

//open in tab
void QbCefViewDelegate::onNewBrowser(const QString& url)
{
    QbBondModule::instance().showWebPage(url);
}

void QbCefViewDelegate::onSendDataToWeb(int browserId, qint64 frameId, const QString &res, const QString &cb)
{
     /*cb.isEmpty() ? QString("onQbResult(%1,%2)").arg(sid).arg(res) :*/
    const QString code = QString("%1(%2)").arg(cb, res);
    executeJavascript(browserId, frameId, code, "");
    //executeJavascript(browserId, frameId, "console.log('----Across the Great Wall?----')", "");

    //log_warning("QbCefViewDelegate::onSendDataToWeb: browserId=%d frame_id=%d, code=%s", browserId, frameId, code.toStdString().c_str());
}
